package taller2.model.graph.algorithms;

import java.util.ArrayList;

import taller2.interfaces.Connection;
import taller2.interfaces.Graph;
import taller2.interfaces.Node;
import taller2.utils.Constants;

public class PrimApplicator extends AlgorithmApplicatorImpl{
    private ArrayList<Node> nodes;
    private static final String savePath = Constants.savedGraphsPath + "Primm";
    
    public PrimApplicator() {
    	super();
    }
    
	@Override
	public void solveProblem(Graph g) {

		if(noGraph(g) || !noGraphPaths() || !noPseudocodeLines())
			return;
		
		g.killFluxes();
		g.unselectConnections();		
		g.unselectNodes();		
	        
		//Salvo estado inicial
		g.save(savePath);
        int cont = 0;

		nodes = g.getNodes();
		Node node = nodes.get(0);

        guardarPaso(g, cont, 0, null, false);
        cont++;

        guardarPaso(g, cont, 1, null, false);
        cont++;

		node.select();

        ArrayList<Node> selectedNodes = new ArrayList<Node>();
		selectedNodes.add(node);

        guardarPaso(g, cont, 2, null, false);
        cont++;

		while (!allSelectedNodes()) {
        	guardarPaso(g, cont, 3, null, false);
            cont++;

		    node = nodeWithMinimalConnection(selectedNodes);

            if (node == null)
            	break;

            guardarPaso(g, cont, 4, null, false);
            cont++;

		    Connection connection = minimalConnectionOfNode(node);
		    if(connection != null){
		    	Node other = connection.getOtherNode();
		        int index2 = nodes.indexOf(other);

		        guardarPaso(g, cont, 5, null, false);
		        cont++;

		        Node newNode = nodes.get(index2);
		        node.selectConnectionsWith(other);

		        guardarPaso(g, cont, 6, null, false);
		        cont++;

		        newNode.select();
		        selectedNodes.add(newNode);
		    }
		}

      	guardarPaso(g, cont, 7, null, false);
        cont++;

		//Listo!, se ejecuto el algoritmo -> cargo el estado inicial para empezar a mostrarlo
		g.load(savePath);
	}

    private boolean allSelectedNodes() {
        for (Node node : nodes) {
            if (!node.isSelected()) {
                return false;
            }
        }
        return true;
    }

    private Connection minimalConnectionOfNode(Node node) {
        Connection minimalConnection =  null;
        if(node != null){
        	for (Connection connection : node.getConnections()) {
        		if ((minimalConnection == null || connection.getWeight() < minimalConnection.getWeight()) && (!connection.isSelected()) && (!connection.getOtherNode().isSelected())) {
        			minimalConnection = connection;
                }
        	}
        }
        return minimalConnection;
    }


    private Node nodeWithMinimalConnection(ArrayList<Node> nodes) {
        Connection minimalConnection =  null;
        Node minimalNode = null;
        for (Node node : nodes) {
            for (Connection connection : node.getConnections()) {
                if ((minimalConnection == null || connection.getWeight() < minimalConnection.getWeight()) && (!connection.isSelected()) && (!connection.getOtherNode().isSelected())) {
                    minimalConnection = connection;
                    minimalNode = node;
                }
            }
        }
        /*if (minimalConnection != null) {
            minimalConnection.select();
        }*/
        return minimalNode;
    }	
    
	public void save(String path){
	};

	public void load(String path){
	};

    private void guardarPaso(Graph g, int cont, int pcLine, Node SelNode, boolean remover){
        saveGraph(g, savePath + cont);
        pseudocodeLines.add(pcLine);
        String aGuardar;
        if ( (remover) && (!auxText.isEmpty()) ){
            String pasoAnterior = auxText.get(auxText.size() - 1);
            int posPrimerSeparador = pasoAnterior.indexOf(" ");

            if (posPrimerSeparador >= 0)
                aGuardar = pasoAnterior.substring(posPrimerSeparador + 3);
            else
                aGuardar = "";

            auxText.add(aGuardar);

            return;
        }

        if ( auxText.isEmpty() ){
            if (SelNode == null){
                auxText.add("");
            }
            else{
				String tag = SelNode.getTag();
				if (tag == null) { tag = Constants.sinTag;}
                auxText.add(" " + tag);
            }
        }else{
            if ((SelNode == null)){
                //si no tengo nada que agregar repito lo ultimo que halla puesto
                auxText.add(auxText.get(auxText.size() - 1));
            }
            else{
                auxText.add(auxText.get(auxText.size() - 1) + " " + SelNode.getTag() + "\n" );
            }
        }

    }

	@Override
	public int getHighlightedWordNumber() {
		return -1;
	}

	public int getGraphCount() {
		int tam = graphPaths.size();

		if(tam == 0)
			tam++;
		
		return tam;
	}

	public String getGraphPath(int pos) {
		if(pos >= graphPaths.size()){
			return "";
		}
		
		return graphPaths.get(pos);
	}
	
}
